using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Xml;

namespace AzureusWrapper
{
    public class AzureusHost
    {
        private Uri hostUri;
        private WebClient webClient;
        private string connectionId = "";
        private int requestId =0;
        private string singletonId;
        private string downloadManagerId;

        public Uri HostUri
        {
            get
            {
                return HostUri;
            }
        }
        
        public AzureusHost(string hostUri)
        {
            this.hostUri = new Uri(hostUri);
            webClient = new WebClient();
            webClient.BaseAddress = hostUri;
            Connect();
        }
        public AzureusHost(Uri hostUri)
        {
            this.hostUri = hostUri;
            webClient = new WebClient();
            webClient.BaseAddress = hostUri.ToString();
            Connect();
        }

        private Request CreateRequest()
        {
            requestId++;
            return new Request(requestId.ToString(),connectionId);
        }
        private void Connect()
        {
            Request getConnectionId = new Request(requestId.ToString(), "");
            getConnectionId.Method = "getSingleton";
            XmlDocument res = SendRequest(getConnectionId).SerializedResponse;
            requestId++;
            singletonId = res.GetElementsByTagName("_object_id")[0].InnerText.Trim();

            Request getDownloadManagerId = CreateRequest();
            getDownloadManagerId.Method = "getDownloadManager";
            getDownloadManagerId.ObjectId = singletonId;
            downloadManagerId = SendRequest(getDownloadManagerId).SerializedResponse.GetElementsByTagName("_object_id")[0].InnerText.Trim();
        }
        private Response SendRequest(Request request)
        {
            webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            string res = webClient.UploadString(hostUri, "POST", SerializeRequest(request));
            return new Response(res);
        }
        private string SerializeRequest(Request request)
        {
            XmlDocument xdoc = new XmlDocument();
                XmlElement requestElement = xdoc.CreateElement("REQUEST");

                    XmlElement methodElement = xdoc.CreateElement("METHOD");
                    methodElement.InnerText = request.Method;
                    requestElement.AppendChild(methodElement);
            
                    XmlElement requestIdElement = xdoc.CreateElement("REQUEST_ID");
                    requestIdElement.InnerText =request.RequestId;
                    requestElement.AppendChild(requestIdElement);
                    
                    if (request.ObjectId != null)
                    {
                        XmlElement objectElement = xdoc.CreateElement("OBJECT");
                        XmlElement objectIdElement = xdoc.CreateElement("_object_id");
                        objectIdElement.InnerText = request.ObjectId;
                        objectElement.AppendChild(objectIdElement);
                        requestElement.AppendChild(objectElement);
                    }
                    if (request.ConnectionId != null && !request.ConnectionId.Equals(""))
                    {
                        XmlElement connectionIdElement = xdoc.CreateElement("CONNECTION_ID");
                        connectionIdElement.InnerText = request.ConnectionId;
                        requestElement.AppendChild(connectionIdElement);
                    }
                    if (request.Params != null && request.Params.Count != 0)
                    {
                        XmlElement paramsElement = xdoc.CreateElement("PARAMS");
                        for (int i = 0; i < request.Params.Count; i++)
                        {
                            XmlElement entryElement = xdoc.CreateElement("ENTRY");
                            entryElement.InnerText = request.Params[i];
                            paramsElement.AppendChild(entryElement);
                        }
                        requestElement.AppendChild(paramsElement);
                    }
            return requestElement.OuterXml;
        }

        public Download[] GetDownloads()
        {
            Request getDownloads = CreateRequest();
            getDownloads.Method = "getDownloads[boolean]";
            getDownloads.ObjectId = downloadManagerId;
            getDownloads.Params.Add("true");
            Response downloadsResponse = SendRequest(getDownloads);
            XmlNodeList entries = downloadsResponse.SerializedResponse.GetElementsByTagName("ENTRY");
            Download[] result = new Download[entries.Count];
            for (int i = 0; i < entries.Count; i++)
            {
                result[i] = new Download(entries[i]);
            }
            return result;
        }
        public void StopDownload(string ObjectId)
        {
            Request stopDownloadRequest = CreateRequest();
            stopDownloadRequest.Method = "stop";
            stopDownloadRequest.ObjectId = ObjectId;

            SendRequest(stopDownloadRequest);
        }
        public void StartDownload(string ObjectId)
        {
            Request startDownloadRequest = CreateRequest();
            startDownloadRequest.Method = "restart";
            startDownloadRequest.ObjectId = ObjectId;
            SendRequest(startDownloadRequest);
        }
        public void AddDownload(Uri torrentSource)
        {
            Request addDownloadRequest = CreateRequest();
            addDownloadRequest.Method = "addDownload[URL]";
            addDownloadRequest.ObjectId = downloadManagerId;
            addDownloadRequest.Params.Add(torrentSource.ToString());
            SendRequest(addDownloadRequest);
        }
        public void RemoveDownload(string ObjectId)
        {
            StopDownload(ObjectId);
            Request removeDownloadRequest = CreateRequest();
            removeDownloadRequest.Method = "remove";
            //removeDownloadRequest.ObjectId = download.ObjectId;
			removeDownloadRequest.ObjectId = ObjectId;
            SendRequest(removeDownloadRequest);
        }

        public void MoveDownloadUp(string ObjectId)
        {
            Request moveUp = CreateRequest();
            moveUp.Method = "moveUp";
            moveUp.ObjectId = ObjectId;
            SendRequest(moveUp);
        }

        public void MoveDownloadDown(string ObjectId)
        {
            Request moveDown = CreateRequest();
            moveDown.Method = "moveDown";
            moveDown.ObjectId = ObjectId;
            SendRequest(moveDown);
        }
        public void StartAllDownloads()
        {
            Request startAllDownloads = CreateRequest();
            startAllDownloads.Method = "startAllDownloads";
            startAllDownloads.ObjectId = downloadManagerId;
            SendRequest(startAllDownloads);
        }
        public void StopAllDownloads()
        {
            Request stopAllDownloads = CreateRequest();
            stopAllDownloads.Method = "stopAllDownloads";
            stopAllDownloads.ObjectId = downloadManagerId;
            SendRequest(stopAllDownloads);
        }
    }
}
